//|||||||||||||||||||||||||||||||||||||||||||||||

#include "Game2State.hpp"
#include "Game2FinishedState.hpp"
#include "GameEntity.hpp"

#include <sstream>
#include <math.h>

//|||||||||||||||||||||||||||||||||||||||||||||||

using namespace Ogre;

//|||||||||||||||||||||||||||||||||||||||||||||||

Game2State::Game2State()
{
    m_bQuit             = false;
	won = false;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::enter()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Entering GameState...");

    m_pSceneMgr = OgreFramework::getSingletonPtr()->m_pRoot->createSceneManager(ST_GENERIC, "GameSceneMgr");
    m_pSceneMgr->setAmbientLight(Ogre::ColourValue(0.7f, 0.7f, 0.7f));

    m_pCamera = m_pSceneMgr->createCamera("GameCamera");
    m_pCamera->setPosition(Vector3(5, 60, 60));
    m_pCamera->lookAt(Vector3(5, 20, 0));
    m_pCamera->setNearClipDistance(5);
//	m_pCamera->setFarClipDistance(1000);	// removed so we can see the skybox

    m_pCamera->setAspectRatio(Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualWidth()) /
        Real(OgreFramework::getSingletonPtr()->m_pViewport->getActualHeight()));

    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);

	// initialise the variables for the key timers and the player's speed
//	timeSinceAPressed = 0;
//	timeSinceDPressed = 0;
	
	playerSpeed = 0;

	progressBarState = 0;
	progressBarSpeed = 0.01;
	progressBarValue = 0;
	buttonA = false;
	buttonB = false;

    buildGUI();

    createScene();
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::pause()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Pausing GameState...");

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::resume()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Resuming GameState...");

    buildGUI();

    OgreFramework::getSingletonPtr()->m_pViewport->setCamera(m_pCamera);
    m_bQuit = false;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::exit()
{
    OgreFramework::getSingletonPtr()->m_pLog->logMessage("Leaving GameState...");

    m_pSceneMgr->destroyCamera(m_pCamera);
	m_pSceneMgr->clearScene();
	GameEntity::entitiesInitialized = false;
    if(m_pSceneMgr)
        OgreFramework::getSingletonPtr()->m_pRoot->destroySceneManager(m_pSceneMgr);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::createScene()
{
	// initialize the entities
	if(!GameEntity::entitiesInitialized)
	{
		GameEntity::InitializeEntites(m_pSceneMgr);
	}

	// set the angles of rotation for the map segments
	angleSR	=	-9;
	angleR	=	-18;
	angleSL	=	9;
	angleL	=	18;

	// load the skybox
	m_pSceneMgr->setSkyBox(true, "SkyBoxes/SceneSkyBox1");

	// set the position of the player
	m_pCamera->setPosition(35.0f, PLAYER2_HEIGHT, -5.0f);
	m_pCamera->pitch(Ogre::Radian(0));

    //m_pSceneMgr->createLight("Light")->setPosition(75,75,75);

	//////////////////////////////////////////////////////////
	//
	//	Load the map segments
	//
	//////////////////////////////////////////////////////////
	
	////////////////////	3 Straight	//////////////////////
	
	//1
	Ogre::Entity* block = m_pSceneMgr->createEntity("MapSeg1", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg1 = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("MapSeg1");
//	mapSeg1->scale(0.5, 0.5, 0.5);
	mapSeg1->attachObject(block);

	//2
	Ogre::Entity* block2 = m_pSceneMgr->createEntity("MapSeg2", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg2 = mapSeg1->createChildSceneNode( "MapSeg2", Ogre::Vector3(0, 0, -98));
	mapSeg2->attachObject(block2);

	//3
	Ogre::Entity* block3 = m_pSceneMgr->createEntity("MapSeg3", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg3 = mapSeg2->createChildSceneNode( "MapSeg3", Ogre::Vector3(0, 0, -98));
	mapSeg3->attachObject(block3);

	////////////////////	4 Slight Right	//////////////////////

	//1
	Ogre::Entity* block4 = m_pSceneMgr->createEntity("MapSeg4", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg4 = mapSeg3->createChildSceneNode( "MapSeg4", Ogre::Vector3(0, 0, -98));
	mapSeg4->attachObject(block4);

	//2
	Ogre::Entity* block5 = m_pSceneMgr->createEntity("MapSeg5", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg5 = mapSeg4->createChildSceneNode( "MapSeg5", Ogre::Vector3(0, 0, -98));
	mapSeg5->yaw(Ogre::Degree(angleSR));
	mapSeg5->attachObject(block5);

	//3
	Ogre::Entity* block6 = m_pSceneMgr->createEntity("MapSeg6", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg6 = mapSeg5->createChildSceneNode( "MapSeg6", Ogre::Vector3(0, 0, -98));
	mapSeg6->yaw(Ogre::Degree(angleSR));
	mapSeg6->attachObject(block6);

	//4
	Ogre::Entity* block7 = m_pSceneMgr->createEntity("MapSeg7", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg7 = mapSeg6->createChildSceneNode( "MapSeg7", Ogre::Vector3(0, 0, -98));
	mapSeg7->yaw(Ogre::Degree(angleSR));
	mapSeg7->attachObject(block7);

	//////////////////////	2 Right	///////////////////////


	Ogre::Entity* block8 = m_pSceneMgr->createEntity("MapSeg8", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg8 = mapSeg7->createChildSceneNode( "MapSeg8", Ogre::Vector3(0, 0, -98));
	mapSeg8->yaw(Ogre::Degree(angleSR));
	mapSeg8->attachObject(block8);

	Ogre::Entity* block9 = m_pSceneMgr->createEntity("MapSeg9", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg9 = mapSeg8->createChildSceneNode( "MapSeg9", Ogre::Vector3(0, 0, -98));
	mapSeg9->yaw(Ogre::Degree(angleR));
	mapSeg9->attachObject(block9);

	//////////////////////	2 Straight	//////////////////////

	Ogre::Entity* block10 = m_pSceneMgr->createEntity("MapSeg10", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg10 = mapSeg9->createChildSceneNode( "MapSeg10", Ogre::Vector3(0, 0, -98));
	mapSeg10->yaw(Ogre::Degree(angleR));
	mapSeg10->attachObject(block10);

	Ogre::Entity* block11 = m_pSceneMgr->createEntity("MapSeg11", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg11 = mapSeg10->createChildSceneNode( "MapSeg11", Ogre::Vector3(0, 0, -98));
	mapSeg11->attachObject(block11);

	//////////////////////	1 Slight Right	//////////////////////

	Ogre::Entity* block12 = m_pSceneMgr->createEntity("MapSeg12", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg12 = mapSeg11->createChildSceneNode( "MapSeg12", Ogre::Vector3(0, 0, -98));
	mapSeg12->attachObject(block12);

	//////////////////////	4 Right	//////////////////////

	//1
	Ogre::Entity* block13 = m_pSceneMgr->createEntity("MapSeg13", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg13 = mapSeg12->createChildSceneNode( "MapSeg13", Ogre::Vector3(0, 0, -98));
	mapSeg13->yaw(Ogre::Degree(angleSR));
	mapSeg13->attachObject(block13);

	//2
	Ogre::Entity* block14 = m_pSceneMgr->createEntity("MapSeg14", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg14 = mapSeg13->createChildSceneNode( "MapSeg14", Ogre::Vector3(0, 0, -98));
	mapSeg14->yaw(Ogre::Degree(angleR));
	mapSeg14->attachObject(block14);

	//3
	Ogre::Entity* block15 = m_pSceneMgr->createEntity("MapSeg15", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg15 = mapSeg14->createChildSceneNode( "MapSeg15", Ogre::Vector3(0, 0, -98));
	mapSeg15->yaw(Ogre::Degree(angleR));
	mapSeg15->attachObject(block15);

	//4
	Ogre::Entity* block16 = m_pSceneMgr->createEntity("MapSeg16", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg16 = mapSeg15->createChildSceneNode( "MapSeg16", Ogre::Vector3(0, 0, -98));
	mapSeg16->yaw(Ogre::Degree(angleR));
	mapSeg16->attachObject(block16);

	//////////////////////	9 Left	//////////////////////

	//1
	Ogre::Entity* block17 = m_pSceneMgr->createEntity("MapSeg17", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg17 = mapSeg16->createChildSceneNode( "MapSeg17", Ogre::Vector3(0, 0, -98));
	mapSeg17->yaw(Ogre::Degree(angleR));
	mapSeg17->attachObject(block17);

	//2
	Ogre::Entity* block18 = m_pSceneMgr->createEntity("MapSeg18", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg18 = mapSeg17->createChildSceneNode( "MapSeg18", Ogre::Vector3(3, 0, -78));
	mapSeg18->yaw(Ogre::Degree(angleL));	
	mapSeg18->attachObject(block18);

	//3
	Ogre::Entity* block19 = m_pSceneMgr->createEntity("MapSeg19", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg19 = mapSeg18->createChildSceneNode( "MapSeg19", Ogre::Vector3(3, 0, -78));
	mapSeg19->yaw(Ogre::Degree(angleL));
	mapSeg19->attachObject(block19);

	//4
	Ogre::Entity* block20 = m_pSceneMgr->createEntity("MapSeg20", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg20 = mapSeg19->createChildSceneNode( "MapSeg20", Ogre::Vector3(3, 0, -78));
	mapSeg20->yaw(Ogre::Degree(angleL));
	mapSeg20->attachObject(block20);

	//5
	Ogre::Entity* block21 = m_pSceneMgr->createEntity("MapSeg21", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg21 = mapSeg20->createChildSceneNode( "MapSeg21", Ogre::Vector3(3, 0, -78));
	mapSeg21->yaw(Ogre::Degree(angleL));
	mapSeg21->attachObject(block21);

	//6
	Ogre::Entity* block22 = m_pSceneMgr->createEntity("MapSeg22", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg22 = mapSeg21->createChildSceneNode( "MapSeg22", Ogre::Vector3(3, 0, -78));
	mapSeg22->yaw(Ogre::Degree(angleL));
	mapSeg22->attachObject(block22);

	//7
	Ogre::Entity* block23 = m_pSceneMgr->createEntity("MapSeg23", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg23 = mapSeg22->createChildSceneNode( "MapSeg23", Ogre::Vector3(3, 0, -78));
	mapSeg23->yaw(Ogre::Degree(angleL));
	mapSeg23->attachObject(block23);

	//8
	Ogre::Entity* block24 = m_pSceneMgr->createEntity("MapSeg24", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg24 = mapSeg23->createChildSceneNode( "MapSeg24", Ogre::Vector3(3, 0, -78));
	mapSeg24->yaw(Ogre::Degree(angleL));
	mapSeg24->attachObject(block24);

	//9
	Ogre::Entity* block25 = m_pSceneMgr->createEntity("MapSeg25", "GroundLeft.mesh");
	Ogre::SceneNode* mapSeg25 = mapSeg24->createChildSceneNode( "MapSeg25", Ogre::Vector3(3, 0, -78));
	mapSeg25->yaw(Ogre::Degree(angleL));
	mapSeg25->attachObject(block25);

	//////////////////////	1 Slight Right	//////////////////////

	Ogre::Entity* block26 = m_pSceneMgr->createEntity("MapSeg26", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg26 = mapSeg25->createChildSceneNode( "MapSeg26", Ogre::Vector3(3, 0, -78));
	mapSeg26->yaw(Ogre::Degree(angleL));
	mapSeg26->attachObject(block26);

	//////////////////////	4 Right	//////////////////////

	//1
	Ogre::Entity* block27 = m_pSceneMgr->createEntity("MapSeg27", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg27 = mapSeg26->createChildSceneNode( "MapSeg27", Ogre::Vector3(0, 0, -98));
	mapSeg27->yaw(Ogre::Degree(angleSR));
	mapSeg27->attachObject(block27);

	//2
	Ogre::Entity* block28 = m_pSceneMgr->createEntity("MapSeg28", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg28 = mapSeg27->createChildSceneNode( "MapSeg28", Ogre::Vector3(0, 0, -98));
	mapSeg28->yaw(Ogre::Degree(angleR));
	mapSeg28->attachObject(block28);

	//3
	Ogre::Entity* block29 = m_pSceneMgr->createEntity("MapSeg29", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg29 = mapSeg28->createChildSceneNode( "MapSeg29", Ogre::Vector3(0, 0, -98));
	mapSeg29->yaw(Ogre::Degree(angleR));
	mapSeg29->attachObject(block29);

	//4
	Ogre::Entity* block30 = m_pSceneMgr->createEntity("MapSeg30", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg30 = mapSeg29->createChildSceneNode( "MapSeg30", Ogre::Vector3(0, 0, -98));
	mapSeg30->yaw(Ogre::Degree(angleR));
	mapSeg30->attachObject(block30);

	//////////////////////	1 Slight Right	//////////////////////

	Ogre::Entity* block31 = m_pSceneMgr->createEntity("MapSeg31", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg31 = mapSeg30->createChildSceneNode( "MapSeg31", Ogre::Vector3(0, 0, -98));
	mapSeg31->yaw(Ogre::Degree(angleR));
	mapSeg31->attachObject(block31);

	//////////////////////	2 Right	//////////////////////////////

	Ogre::Entity* block32 = m_pSceneMgr->createEntity("MapSeg32", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg32 = mapSeg31->createChildSceneNode( "MapSeg32", Ogre::Vector3(0, 0, -98));
	mapSeg32->yaw(Ogre::Degree(angleSR));
	mapSeg32->attachObject(block32);

	Ogre::Entity* block33 = m_pSceneMgr->createEntity("MapSeg33", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg33 = mapSeg32->createChildSceneNode( "MapSeg33", Ogre::Vector3(0, 0, -98));
	mapSeg33->yaw(Ogre::Degree(angleR));
	mapSeg33->attachObject(block33);

	//////////////////////	4 Slight Right	//////////////////////
	
	//1
	Ogre::Entity* block34 = m_pSceneMgr->createEntity("MapSeg34", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg34 = mapSeg33->createChildSceneNode( "MapSeg34", Ogre::Vector3(0, 0, -98));
	mapSeg34->yaw(Ogre::Degree(angleR));
	mapSeg34->attachObject(block34);

	//2
	Ogre::Entity* block35 = m_pSceneMgr->createEntity("MapSeg35", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg35 = mapSeg34->createChildSceneNode( "MapSeg35", Ogre::Vector3(0, 0, -98));
	mapSeg35->yaw(Ogre::Degree(angleSR));
	mapSeg35->attachObject(block35);

	//3
	Ogre::Entity* block36 = m_pSceneMgr->createEntity("MapSeg36", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg36 = mapSeg35->createChildSceneNode( "MapSeg36", Ogre::Vector3(0, 0, -98));
	mapSeg36->yaw(Ogre::Degree(angleSR));
	mapSeg36->attachObject(block36);

	//4
	Ogre::Entity* block37 = m_pSceneMgr->createEntity("MapSeg37", "GroundSlightRight.mesh");
	Ogre::SceneNode* mapSeg37 = mapSeg36->createChildSceneNode( "MapSeg37", Ogre::Vector3(0, 0, -98));
	mapSeg37->yaw(Ogre::Degree(angleSR));
	mapSeg37->attachObject(block37);

	//////////////////////	3 Straight Right	//////////////////////

	//1
	Ogre::Entity* block38 = m_pSceneMgr->createEntity("MapSeg38", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg38 = mapSeg37->createChildSceneNode( "MapSeg38", Ogre::Vector3(0, 0, -98));
	mapSeg38->yaw(Ogre::Degree(angleSR));
	mapSeg38->attachObject(block38);

	//2
	Ogre::Entity* block39 = m_pSceneMgr->createEntity("MapSeg39", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg39 = mapSeg38->createChildSceneNode( "MapSeg39", Ogre::Vector3(0, 0, -98));
	mapSeg39->attachObject(block39);

	//3
	Ogre::Entity* block40 = m_pSceneMgr->createEntity("MapSeg40", "GroundStraight.mesh");
	Ogre::SceneNode* mapSeg40 = mapSeg39->createChildSceneNode( "MapSeg40", Ogre::Vector3(0, 0, -98));
	mapSeg40->attachObject(block40);

	//////////////////////	Some Curves to Finish	//////////////////////

	Ogre::Entity* block41 = m_pSceneMgr->createEntity("MapSeg41", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg41 = mapSeg40->createChildSceneNode( "MapSeg41", Ogre::Vector3(0, 0, -95));
	mapSeg41->attachObject(block41);

	Ogre::Entity* block42 = m_pSceneMgr->createEntity("MapSeg42", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg42 = mapSeg41->createChildSceneNode( "MapSeg42", Ogre::Vector3(0, 0, -95));
	mapSeg42->yaw(Ogre::Degree(angleSR));
	mapSeg42->attachObject(block42);

	Ogre::Entity* block43 = m_pSceneMgr->createEntity("MapSeg43", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg43 = mapSeg42->createChildSceneNode( "MapSeg43", Ogre::Vector3(0, 0, -95));
	mapSeg43->yaw(Ogre::Degree(angleSR));
	mapSeg43->attachObject(block43);

	Ogre::Entity* block44 = m_pSceneMgr->createEntity("MapSeg44", "GroundRight.mesh");
	Ogre::SceneNode* mapSeg44 = mapSeg43->createChildSceneNode( "MapSeg44", Ogre::Vector3(0, 0, -95));
	mapSeg44->yaw(Ogre::Degree(angleSR));
	mapSeg44->attachObject(block44);


	
	// load the hazards
	Ogre::SceneNode* hazardsNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("HazardsNode");

	Ogre::SceneNode* hazardNode1 = hazardsNode->createChildSceneNode("HazardNode1");
	hazardNode1->translate(31, 3.5, -120);
	hazardNode1->scale(0.2f, 0.2f, 0.2f);
	hazardNode1->yaw(Ogre::Degree(180));
	hazardNode1->attachObject(GameEntity::Bottle.getNewEntity());

	Ogre::SceneNode* hazardNode2 = hazardsNode->createChildSceneNode("HazardNode2");
	hazardNode2->translate(33, 3.5, -181);
	hazardNode2->scale(0.5f, 0.5f, 0.5f);
	hazardNode2->attachObject(GameEntity::Pill.getNewEntity());

	Ogre::SceneNode* hazardNode3 = hazardsNode->createChildSceneNode("HazardNode3");
	hazardNode3->translate(49, 3.5, -496);
	hazardNode3->scale(0.2f, 0.2f, 0.2f);
	hazardNode3->yaw(Ogre::Degree(180));
	hazardNode3->attachObject(GameEntity::Bottle.getNewEntity());

	
	Ogre::SceneNode* hazardNode4 = hazardsNode->createChildSceneNode("HazardNode4");
	hazardNode4->translate(98, 3.5, -601);
	hazardNode4->scale(0.5f, 0.5f, 0.5f);
	hazardNode4->attachObject(GameEntity::Pill.getNewEntity());

	Ogre::SceneNode* hazardNode5 = hazardsNode->createChildSceneNode("HazardNode5");
	hazardNode5->translate(98, 3.5, -601);
	hazardNode5->scale(0.2f, 0.2f, 0.2f);
	hazardNode5->yaw(Ogre::Degree(180));
	hazardNode5->attachObject(GameEntity::Bottle.getNewEntity());

	Ogre::SceneNode* hazardNode6 = hazardsNode->createChildSceneNode("HazardNode6");
	hazardNode6->translate(214, 3.5, -751);
	hazardNode6->scale(0.5f, 0.5f, 0.5f);
	hazardNode6->attachObject(GameEntity::Pill.getNewEntity());

	Ogre::SceneNode* hazardNode7 = hazardsNode->createChildSceneNode("HazardNode7");
	hazardNode7->translate(214, 3.5, -751);
	hazardNode7->scale(0.2f, 0.2f, 0.2f);
	hazardNode7->yaw(Ogre::Degree(180));
	hazardNode7->attachObject(GameEntity::Bottle.getNewEntity());

	Ogre::SceneNode* hazardNode8 = hazardsNode->createChildSceneNode("HazardNode8");
	hazardNode8->translate(474, 3.5, -855);
	hazardNode8->scale(0.2f, 0.2f, 0.2f);
	hazardNode8->yaw(Ogre::Degree(180));
	hazardNode8->attachObject(GameEntity::Bottle.getNewEntity());

	Ogre::SceneNode* hazardNode9 = hazardsNode->createChildSceneNode("HazardNode9");
	hazardNode9->translate(661, 3.5, -872);
	hazardNode9->scale(0.2f, 0.2f, 0.2f);
	hazardNode9->yaw(Ogre::Degree(180));
	hazardNode9->attachObject(GameEntity::Bottle.getNewEntity());

	Ogre::SceneNode* hazardNode10 = hazardsNode->createChildSceneNode("HazardNode10");
	hazardNode10->translate(870, 3.5, -681);
	hazardNode10->scale(0.2f, 0.2f, 0.2f);
	hazardNode10->yaw(Ogre::Degree(180));
	hazardNode10->attachObject(GameEntity::Bottle.getNewEntity());


	// loads the bonus
	Ogre::SceneNode* BonusesNode = m_pSceneMgr->getRootSceneNode()->createChildSceneNode("BonusesNode");

	Ogre::SceneNode* BonusNode1 = BonusesNode->createChildSceneNode("BonusNode1");
	BonusNode1->translate(42, 3.5, -420);
	BonusNode1->yaw(Ogre::Radian(90));
	BonusNode1->scale(0.5, 4, 4);
	BonusNode1->attachObject(GameEntity::Pillow.getNewEntity());

	Ogre::SceneNode* BonusNode2 = BonusesNode->createChildSceneNode("BonusNode2");
	BonusNode2->translate(147, 3.5, -697);
	BonusNode2->yaw(Ogre::Radian(90));
	BonusNode2->scale(0.5, 4, 4);
	BonusNode2->attachObject(GameEntity::Pillow.getNewEntity());

	Ogre::SceneNode* BonusNode3 = BonusesNode->createChildSceneNode("BonusNode3");
	BonusNode3->translate(379, 3.5, -819);
	BonusNode3->yaw(Ogre::Radian(90));
	BonusNode3->scale(0.5, 4, 4);
	BonusNode3->attachObject(GameEntity::Pillow.getNewEntity());

	Ogre::SceneNode* BonusNode4 = BonusesNode->createChildSceneNode("BonusNode4");
	BonusNode4->translate(750, 3.5, -833);
	BonusNode4->yaw(Ogre::Radian(90));
	BonusNode4->scale(0.5, 4, 4);
	BonusNode4->attachObject(GameEntity::Pillow.getNewEntity());

	Ogre::SceneNode* BonusNode5 = BonusesNode->createChildSceneNode("BonusNode5");
	BonusNode5->translate(1023, 3.5, -579);
	BonusNode5->yaw(Ogre::Radian(90));
	BonusNode5->scale(0.5, 4, 4);
	BonusNode5->attachObject(GameEntity::Pillow.getNewEntity());
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::keyPressed(const OIS::KeyEvent &keyEventRef)
{
    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_ESCAPE))
    {
        m_bQuit = true;
        return true;
    }

    if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_SPACE))
    {
		std::ostringstream  name;
		name << "x=" << m_pCamera->getPosition().x << "  z=" << m_pCamera->getPosition().z;

		OgreFramework::getSingletonPtr()->m_pLog->logMessage(name.str());
        return true;
    }

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::keyReleased(const OIS::KeyEvent &keyEventRef)
{
    if(OgreFramework::getSingletonPtr()->keyReleased(keyEventRef)) return true;

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::mouseMoved(const OIS::MouseEvent &evt)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseMove(evt)) return true;

	m_pCamera->yaw(Degree(evt.state.X.rel * -0.1f));
    m_pCamera->pitch(Degree(evt.state.Y.rel * -0.1f));
	
    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseDown(evt, id)) return true;

    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

bool Game2State::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    if(OgreFramework::getSingletonPtr()->m_pTrayMgr->injectMouseUp(evt, id)) return true;


    return true;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::onLeftPressed(const OIS::MouseEvent &evt)
{
	
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::moveCamera(double timeSinceLastFrame)
{
	float timer = timeSinceLastFrame;


	// Code to handle the direction of movement and speed of the progress bar
	if ((progressBarState == 1) && (progressBarValue < 1))
	{
		progressBarValue += progressBarSpeed;
	}
	else if ((progressBarState == 1) && (progressBarValue > 1))
	{
		progressBarState = -1;
	}
	else if ((progressBarState == -1) && (progressBarValue > 0))
	{
		progressBarValue -= progressBarSpeed;
	}
	else if ((progressBarState == -1) && (progressBarValue < 0))
	{
		progressBarState = 0;
		progressBarValue = 0;
	}

	// Code to handle what happens if a user runs out of time to hit a button
	if ((progressBarValue == 0) && (playerSpeed))
	{
		if (progressBarSpeed > 0) progressBarSpeed -= 0.001;
		else if (progressBarSpeed <= 0) progressBarSpeed = 0;

		if (playerSpeed > 0) playerSpeed -= 0.02;
		else if (playerSpeed <= 0) playerSpeed = 0;		
	}


//	playerSpeed -= timer/1000;

	
	/////////////////// Conditions for A being Pressed

	if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_A)
		|| OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_Q))
    {
		buttonB = false;	// set buttonB to false so that the player can use it

		if (buttonA == false)
		{
			buttonA = true;

			if ((progressBarValue >= 0.8) && (progressBarValue < 1))	// speed up
			{
				if (progressBarSpeed < 0.02) progressBarSpeed += 0.005;
				else if (progressBarSpeed >= 0.02) progressBarSpeed = 0.02;

				if (playerSpeed < 1) playerSpeed += 0.2;
				else if (playerSpeed >= 1) playerSpeed = 1;
			}
			else if ((progressBarValue > 0) && (progressBarValue < 0.5))	// slow down
			{
				if (progressBarSpeed > 0) progressBarSpeed -= 0.005;
				else if (progressBarSpeed <= 0) progressBarSpeed = 0;

				if (playerSpeed > 0) playerSpeed -= 0.2;
				else if (playerSpeed <= 0) playerSpeed = 0;				
			}
			else if ((progressBarValue <= 0) || (playerSpeed <= 0))	// condition only met if starting from a standstill or a bug occurs
			{
				progressBarSpeed += 0.005;
				playerSpeed += 0.2;
			}
			
			progressBarValue = 0;
			progressBarState = 1;
		}
	} 

	/////////////////// Conditions for D being Pressed

	else if(OgreFramework::getSingletonPtr()->m_pKeyboard->isKeyDown(OIS::KC_D)) 
	{
		buttonA = false;	// set buttonB to false so that the player can use it

		if (buttonB == false)
		{
			buttonB = true;

			if ((progressBarValue >= 0.8) && (progressBarValue < 1))	// speed up
			{
				if (progressBarSpeed < 0.02) progressBarSpeed += 0.005;
				else if (progressBarSpeed >= 0.02) progressBarSpeed = 0.02;

				if (playerSpeed < 1) playerSpeed += 0.2;
				else if (playerSpeed >= 1) playerSpeed = 1;
			}
			else if ((progressBarValue > 0) && (progressBarValue < 0.5))	// slow down
			{
				if (progressBarSpeed > 0) progressBarSpeed -= 0.005;
				else if (progressBarSpeed <= 0) progressBarSpeed = 0;

				if (playerSpeed > 0) playerSpeed -= 0.2;
				else if (playerSpeed <= 0) playerSpeed = 0;				
			}
			else if ((progressBarValue <= 0) || (playerSpeed <= 0))	// condition only met if starting from a standstill or a bug occurs
			{
				progressBarSpeed += 0.005;
				playerSpeed += 0.2;
			}
			
			progressBarValue = 0;
			progressBarState = 1;
		}
	}	

	bar->setProgress(progressBarValue);

	Ogre::Vector3 direction(m_pCamera->getRealDirection());

	direction.y = 0;
	direction.normalise();
	direction.x *= playerSpeed;
	direction.z *= playerSpeed;

	m_pCamera->move(direction);

}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::getInput()
{
	
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::update(double timeSinceLastFrame)
{
    m_FrameEvent.timeSinceLastFrame = timeSinceLastFrame;
    OgreFramework::getSingletonPtr()->m_pTrayMgr->frameRenderingQueued(m_FrameEvent);

    if(m_bQuit == true)
    {
        popAppState();
        return;
    }
	
	timeLeftBar->setProgress(timeLeftBar->getProgress() 
		+ PROGRESS2_PER_MILISECOND*timeSinceLastFrame);

    getInput();

	moveCamera(timeSinceLastFrame);
	checkBorderCollision(); // update the position according to the path

	updateHazardsAndBonusesCollisions();
	checkVictoryOrLose();
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::buildGUI()
{
//	OgreFramework::getSingletonPtr()->m_pTrayMgr->createCheckBox(OgreBites::TL_CENTER, "Instructions", "Press the run keys (A or D) at the point where the progress bar is full to maintain the fastest speed! Pressing A/D at any other time will slow you down...", 500);

    OgreFramework::getSingletonPtr()->m_pTrayMgr->showFrameStats(OgreBites::TL_BOTTOMLEFT);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->showLogo(OgreBites::TL_BOTTOMRIGHT);
    OgreFramework::getSingletonPtr()->m_pTrayMgr->hideCursor();

//	OgreFramework::getSingletonPtr()->m_pTrayMgr->createLabel(OgreBites::TL_BOTTOM, "PressA", "Press A!", 250);
	bar = OgreFramework::getSingletonPtr()->m_pTrayMgr->createProgressBar(OgreBites::TL_BOTTOM, "PressA", "Press A/D when the bar is at its fullest to speed up!" , 500, 0);	

	timeLeftBar = OgreFramework::getSingletonPtr()->m_pTrayMgr->createProgressBar(OgreBites::TL_TOP, "TimeLeft", "Time Remaining:", 500, 0);	
	timeLeftBar->setProgress(1.0f);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::itemSelected(OgreBites::SelectMenu* menu)
{
	
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::winGame()
{
	Game2FinishedState* state = (Game2FinishedState*) findByName("Game2FinishedState");

	state->setGameWon(true);
	changeAppState(state);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::loseGame()
{
	Game2FinishedState* state = (Game2FinishedState*) findByName("Game2FinishedState");

	state->setGameWon(false);
	changeAppState(state);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::checkBorderCollision()
{
	// create a vector from the player position
	Ogre::Vector3 playerPosition(
		m_pCamera->getRealPosition().x,
		m_pCamera->getRealPosition().y, // not used
		m_pCamera->getRealPosition().z);

	// get the first node
	Ogre::SceneNode* currentSection = 
		(Ogre::SceneNode*) (m_pSceneMgr->getRootSceneNode()->getChild("MapSeg1"));

	// computes the correct position
	checkBorderCollision(currentSection, 
								playerPosition,
								Ogre::Vector3(0, 0, 0), 0.0f);

	// update the player's position
	m_pCamera->setPosition(playerPosition);
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::checkBorderCollision(Ogre::SceneNode* currentSection, 
									  Ogre::Vector3 &playerPosition,
									  Ogre::Vector3 parentPosition,
									  float angle)
{
	
	// computes the position of the bounding box in the new coordinate systems
	// translate
	playerPosition.x -= parentPosition.x;
	playerPosition.z -= parentPosition.z;
	// rotate
	float newX = playerPosition.x*cos(angle)-playerPosition.z*sin(angle);
	float newZ = playerPosition.x*sin(angle)+playerPosition.z*cos(angle);

	playerPosition.x = newX;
	playerPosition.z = newZ;

	// now check if the camera in in this section, not too far...
	if(playerPosition.z <= 5.0f
		&& playerPosition.z >= -SECTION_LENGTH
		&& playerPosition.x >= 0.0f
		&& playerPosition.x <= 70.0f)
	{
		if(currentSection->getName() == "MapSeg40")
		{
			won = true;
		}

		// if yes do the test
		if(playerPosition.x <= SECTION_X_PATH_BEGIN)
		{
			playerPosition.x = SECTION_X_PATH_BEGIN + 0.1f;
		}
		else if(playerPosition.x >= SECTION_X_PATH_END)
		{
			playerPosition.x = SECTION_X_PATH_END - 0.1f;
		}
	}
	else // else call reccursively
	{
		// computes the new node, position and orientation 
		Ogre::SceneNode* newSection = (Ogre::SceneNode*) currentSection->getChild(0);

		if(newSection)
		{
			Ogre::Vector3 newParentPosition(
				newSection->getPosition().x,
				0.0f,
				newSection->getPosition().z);

			float newAngle = newSection->getOrientation().getYaw().valueRadians();

			checkBorderCollision(newSection, playerPosition,
								newParentPosition, newAngle);
		}
	}

	// changes back the axis for the position
	// rotate back
	float backX = playerPosition.x*cos(angle)+playerPosition.z*sin(angle);
	float backZ = -playerPosition.x*sin(angle)+playerPosition.z*cos(angle);
	
	playerPosition.x = backX;
	playerPosition.z = backZ;

	// translate back
	playerPosition.x += parentPosition.x;
	playerPosition.z += parentPosition.z;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::updateHazardsAndBonusesCollisions()
{
	// computes the player bounding box
	Ogre::AxisAlignedBox playerBoundingBox(
		m_pCamera->getRealPosition().x - PLAYER2_OFFSET,
		m_pCamera->getRealPosition().y - PLAYER2_HEIGHT,
		m_pCamera->getRealPosition().z - PLAYER2_OFFSET,
		m_pCamera->getRealPosition().x + PLAYER2_OFFSET,
		m_pCamera->getRealPosition().y + PLAYER2_OFFSET,
		m_pCamera->getRealPosition().z + PLAYER2_OFFSET);

	Ogre::SceneNode * collideNode = checkCollisionWithHazards(playerBoundingBox);

	if(collideNode)
	{
		// collision with an hazard
		collideNode->detachAllObjects();
		collideNode->getParent()->removeChild(collideNode->getName());
		timeLeftBar->setProgress(timeLeftBar->getProgress() + PROGRESS2_PER_HAZARD);
		
		if (progressBarSpeed > 0) progressBarSpeed -= 0.01;
		else if (progressBarSpeed <= 0) progressBarSpeed = 0;

		if (playerSpeed > 0) playerSpeed -= 0.4;
		else if (playerSpeed <= 0) playerSpeed = 0;		
	}

	// check the collision with a bonus
	collideNode = checkCollisionWithBonuses(playerBoundingBox);

	if(collideNode)
	{
		// collision with a bonus
		collideNode->detachAllObjects();
		collideNode->getParent()->removeChild(collideNode->getName());
		timeLeftBar->setProgress(timeLeftBar->getProgress() + PROGRESS2_PER_BONUS);
		if(timeLeftBar->getProgress() >= 1.0f)
		{
			timeLeftBar->setProgress(1.0f);
		}

		if (progressBarSpeed < 0.02) progressBarSpeed += 0.005;
		else if (progressBarSpeed >= 0.02) progressBarSpeed = 0.02;

		if (playerSpeed < 1) playerSpeed += 0.2;
		else if (playerSpeed >= 1) playerSpeed = 1;
	}
}

//|||||||||||||||||||||||||||||||||||||||||||||||

void Game2State::checkVictoryOrLose()
{
	if(timeLeftBar->getProgress() <= 0.0f) // no time left
	{
		loseGame();
		return;
	}

	if(won)
	{
		won = false;
		winGame();
	}
}

//|||||||||||||||||||||||||||||||||||||||||||||||

Ogre::SceneNode* Game2State::checkCollisionWithHazards(Ogre::AxisAlignedBox &box)
{
	Ogre::Node::ChildNodeIterator it = 
		m_pSceneMgr->getRootSceneNode()->getChild("HazardsNode")->getChildIterator();

	Ogre::SceneNode* currentNode;

	while(it.hasMoreElements())
	{
		 currentNode = dynamic_cast<Ogre::SceneNode*>(it.getNext());

		 Ogre::SceneNode::ObjectIterator entityIt = currentNode->getAttachedObjectIterator();

		 Ogre::Entity* currentEntity;

		 while(entityIt.hasMoreElements())
		{
			currentEntity = dynamic_cast<Ogre::Entity*>(entityIt.getNext());

			Ogre::AxisAlignedBox playerBox(box);

			playerBox.getMinimum().x -= currentNode->getPosition().x;
			playerBox.getMinimum().y -= currentNode->getPosition().y;
			playerBox.getMinimum().z -= currentNode->getPosition().z;
			playerBox.getMinimum().x = playerBox.getMinimum().x / currentNode->getScale().x;
			playerBox.getMinimum().y = playerBox.getMinimum().y / currentNode->getScale().y;
			playerBox.getMinimum().z = playerBox.getMinimum().z / currentNode->getScale().z;

			playerBox.getMaximum().x -= currentNode->getPosition().x;
			playerBox.getMaximum().y -= currentNode->getPosition().y;
			playerBox.getMaximum().z -= currentNode->getPosition().z;
			playerBox.getMaximum().x = playerBox.getMaximum().x / currentNode->getScale().x;
			playerBox.getMaximum().y = playerBox.getMaximum().y / currentNode->getScale().y;
			playerBox.getMaximum().z = playerBox.getMaximum().z / currentNode->getScale().z;

			// check collision
			if(currentEntity->getBoundingBox().intersects(playerBox))
			{
				return currentNode;
			}
		}
	}

	return NULL;
}

//|||||||||||||||||||||||||||||||||||||||||||||||

Ogre::SceneNode* Game2State::checkCollisionWithBonuses(Ogre::AxisAlignedBox &box)
{
	Ogre::Node::ChildNodeIterator it = 
		m_pSceneMgr->getRootSceneNode()->getChild("BonusesNode")->getChildIterator();

	Ogre::SceneNode* currentNode;

	while(it.hasMoreElements())
	{
		 currentNode = dynamic_cast<Ogre::SceneNode*>(it.getNext());

		 Ogre::SceneNode::ObjectIterator entityIt = currentNode->getAttachedObjectIterator();

		 Ogre::Entity* currentEntity;

		 while(entityIt.hasMoreElements())
		{
			currentEntity = dynamic_cast<Ogre::Entity*>(entityIt.getNext());

			Ogre::AxisAlignedBox playerBox(box);

			playerBox.getMinimum().x -= currentNode->getPosition().x;
			playerBox.getMinimum().y -= currentNode->getPosition().y;
			playerBox.getMinimum().z -= currentNode->getPosition().z;
			playerBox.getMinimum().x = playerBox.getMinimum().x / currentNode->getScale().x;
			playerBox.getMinimum().y = playerBox.getMinimum().y / currentNode->getScale().y;
			playerBox.getMinimum().z = playerBox.getMinimum().z / currentNode->getScale().z;

			playerBox.getMaximum().x -= currentNode->getPosition().x;
			playerBox.getMaximum().y -= currentNode->getPosition().y;
			playerBox.getMaximum().z -= currentNode->getPosition().z;
			playerBox.getMaximum().x = playerBox.getMaximum().x / currentNode->getScale().x;
			playerBox.getMaximum().y = playerBox.getMaximum().y / currentNode->getScale().y;
			playerBox.getMaximum().z = playerBox.getMaximum().z / currentNode->getScale().z;

			// check collision
			if(currentEntity->getBoundingBox().intersects(playerBox))
			{
				return currentNode;
			}
		}
	}

	return NULL;
}